<?php

/**
 * @author 		Samuel Carlier
 * @package 	P3Base_Mailer
 * @subpackage 	P3Base_Mailer_Handler
 */
class P3Base_Mailer_Handler_SMTP extends P3Base_Socket_SMTP {

	/**
	 * @var int
	 */
	protected $_buffer = 65536; // 64kb
	
	/**
	 * @var file resource
	 */
	protected $_file_resource = null;

	/**
	 * @param P3Base_Mailer_Envelope $envelope
	 */
	public function perform(P3Base_Mailer_Envelope $envelope) {
		$hasInlineImages = $this->_inlineImages($envelope);

		$this->_connect();

		$addresses 	= $envelope->getAddresses();
		$message	= $envelope->getMessage();
		$headers 	= $envelope->getHeaders();
		$files		= $envelope->getFiles();

		//from
		$from 		= $addresses->getIterator('from');
		$returnPath = $addresses->getIterator('return_path');
		$this->_setFrom(!is_null($returnPath->current()) ? $returnPath->key() : $from->key());

		//rcpt
		$types = array('to','cc','bcc');
		while(list(,$type) = each($types)) {
			$iterator = $addresses->getIterator($type);
			
			$emails = '';
			foreach($iterator as $email => $value) {
				$emails .= $value . ',';
				$this->_setRCPT($email);
			}
			
			if($emails !== '') {
				$headers->add(ucfirst($type), substr($emails, 0, -1));
			}
		}

		$this->_startData();

		//append headers
		$headers->add('From', $from->current());

		if(!is_null($returnPath->current())) {
			$headers->add('Return-Path', $returnPath->current(), false);
		}
		
		$receiptTo = $addresses->getIterator('receipt_to')->current();
		if(!is_null($receiptTo)) {
			$headers->add('Return-Receipt-To', $receiptTo, false);
		}
		
		$replayTo = $addresses->getIterator('replay_to')->current();
		if(!is_null($replayTo)) {
			$headers->add('Reply-To', $replayTo, false);
		}

		$headers->add('Subject'		, $message->getSubject());
		$headers->add('Date'		, date('r')	, false);
		$headers->add('Mime-Version', '1.0'		, false);
		$headers->add('X-Mailer'	, 'P3Mailer', false);
		$headers->add('Message-ID'	, '<' . uniqid(date('\p\3_YmdHis_')) . '>', false);

		//check if we got attachments
		if($files->getIterator()->valid()) {
			$mixed_boundry = md5(uniqid('mixed_'));
			
			if($hasInlineImages) {
				//$headers->add('Content-Type', 'multipart/related; type="multipart/alternative"; boundary='.$mixed_boundry);
				$headers->add('Content-Type', 'multipart/related; boundary='.$mixed_boundry);
	
			} else {
				$headers->add('Content-Type', 'multipart/mixed; boundary='.$mixed_boundry);
			}	
		}

		$content = '';
		foreach($headers->getIterator() as $header) {
			$content .= $header;
		}

		if(isset($mixed_boundry)) {
			$content .= '--' . $mixed_boundry . P3Base_Socket_Client::CRLF;
		}
	
		$content .= $message->getMailMessage();
		$this->_write($content);

		//files
		foreach($files->getIterator() as $file_path => $file) {
	
			$this->_write('--' . $mixed_boundry . P3Base_Socket_Client::CRLF . $file);

			while(($content = $this->_readFile($file_path)) !== false) {
				$this->_write($content, false);
			}
			
			$this->_write(P3Base_Socket_Client::CRLF);
		}

		if(isset($mixed_boundry)) {
			$this->_write('--' . $mixed_boundry . '--');
		}

		//end data
		$this->_endData();
		$this->_reset();
	}
	
	/**
	 * @param  string $path
	 * @return string
	 */
	private function _readFile($file_path) {
		if(is_null($this->_file_resource)) {
			$this->_file_resource = fopen($file_path, 'rb');
			
			$params = array('line-length' => 76, 'line-break-chars' => P3Base_Socket_Client::CRLF);
			stream_filter_append($this->_file_resource, 'convert.base64-encode', STREAM_FILTER_READ, $params);
		}

		if(feof($this->_file_resource)) {
			fclose($this->_file_resource);
			$this->_file_resource = null;
			return false;	
		}
		
		$content = @fread($this->_file_resource, $this->_buffer);
		if($content === false) {
			$this->close();
			throw new P3Base_Mailer_Handler_Exception(P3Base_Language_Translator::get('read_error'));
		}

		return $content;
	}
	
	/**
	 * check if there are inline images
	 * and add them to the P3Base_Mailer_Files instance
	 * 
	 * @param P3Base_Mailer_Envelope $envelope
	 */
	private function _inlineImages($envelope) {
		if(!$envelope->getMessage()->hasHTML()) {
			return false;
		}
		
		$html = $envelope->getMessage()->getHTML()->getContent();
		
		preg_match_all('/<img[^>]+src=\"([^\"]+)/i', $html, $images);

		$file_index  = $envelope->getFiles()->count();
		$images 	 = array_unique($images[1]);
		$image_count = count($images);

		if($image_count == 0) {
			return false;	
		}

		foreach($images as $image) {
			if(!file_exists($image)) {
				throw new P3Base_Mailer_Handler_Exception('Cannot find file: ' . $image);	
			}

			$envelope->addFile($image, '', 'auto');	
		}

		$files = $envelope->getFiles()->get();
		for($i = 0; $i < $image_count; $i++) {
			$file = $files[$file_index + $i];
			$html = str_replace('src="'.$images[$i].'"', 'src="cid:'.$file['content_id'].'"', $html);
		}

		$encoding = $envelope->getMessage()->getHTML()->getEncoding();
		$envelope->setHTMLMessage($html, $encoding);

		return true;
	}
	
	/**
	 * close if not done by user
	 */
	public function __destruct() {
//		$this->close();	
	}
}

?>
